﻿using System;
using System.Threading;
using System.Threading.Tasks;

namespace InDepth2Demo.Chapter15
{
    /// <summary>
    /// 异步VS多线程
    /// 异步编程（Asynchronous）
    /// 多线程编程（Multithreading）
    /// </summary>
    internal class AsyncVsMultiThread
    {
        // 异步编程的代码
        public static async Task FirstAsync()
        {
            Console.WriteLine($"第一个异步方法开始，运行的线程ID为：{Thread.CurrentThread.ManagedThreadId}");
            await Task.Delay(2000);
            Console.WriteLine($"第一个异步方法结束，运行的线程ID为：{Thread.CurrentThread.ManagedThreadId}");
        }
        public static async Task SecondAsync()
        {
            Console.WriteLine($"第二个异步方法开始，运行的线程ID为：{Thread.CurrentThread.ManagedThreadId}");
            await Task.Delay(2000);
            Console.WriteLine($"第二个异步方法结束，运行的线程ID为：{Thread.CurrentThread.ManagedThreadId}");
        }
        public static async Task ThirdAsync()
        {
            Console.WriteLine($"第三个异步方法开始，运行的线程ID为：{Thread.CurrentThread.ManagedThreadId}");
            await Task.Delay(2000);
            Console.WriteLine($"第三个异步方法结束，运行的线程ID为：{Thread.CurrentThread.ManagedThreadId}");
        }

        // 添加一个异步方法来调用上面的异步方法
        public static async Task ExecuteAysnc()
        {
            var firstAsync = FirstAsync();
            var secondAsync = SecondAsync();
            var thirdAsync = ThirdAsync();
            await Task.WhenAll(firstAsync, secondAsync, thirdAsync);

            // 输出
            //第一个异步方法开始，运行的线程ID为：1
            //第二个异步方法开始，运行的线程ID为：1
            //第三个异步方法开始，运行的线程ID为：1
            //第三个异步方法结束，运行的线程ID为：4
            //第二个异步方法结束，运行的线程ID为：5
            //第一个异步方法结束，运行的线程ID为：7

            // 当线程发现关键字await的时候，该线程就会从当前逻辑释放而返回给线程池。一旦睡眠结束，一个新的线程（4、7、5）就重新被分配来执行三个任务。
        }


        // 多线程的代码示例
        public static void FirstMethod()
        {
            Console.WriteLine($"第一个方法开始，运行的线程ID为：{Thread.CurrentThread.ManagedThreadId}");
            Thread.Sleep(2000);
            Console.WriteLine($"第一个方法结束，运行的线程ID为：{Thread.CurrentThread.ManagedThreadId}");
        }
        public static void SecondMethod()
        {
            Console.WriteLine($"第二个方法开始，运行的线程ID为：{Thread.CurrentThread.ManagedThreadId}");
            Thread.Sleep(2000);
            Console.WriteLine($"第二个方法结束，运行的线程ID为：{Thread.CurrentThread.ManagedThreadId}");
        }
        public static void ThirdMethod()
        {
            Console.WriteLine($"第三个方法开始，运行的线程ID为：{Thread.CurrentThread.ManagedThreadId}");
            Thread.Sleep(2000);
            Console.WriteLine($"第三个方法结束，运行的线程ID为：{Thread.CurrentThread.ManagedThreadId}");
        }

        public static void ExecuteMultithreading()
        {
            Thread firstThread = new Thread(() => FirstMethod());
            Thread secondThread = new Thread(() => SecondMethod());
            Thread thirdThread = new Thread(() => ThirdMethod());

            firstThread.Start();
            secondThread.Start();
            thirdThread.Start();

            //第二个方法开始，运行的线程ID为：4
            //第三个方法开始，运行的线程ID为：5
            //第一个方法开始，运行的线程ID为：3
            //第二个方法结束，运行的线程ID为：4
            //第一个方法结束，运行的线程ID为：3
            //第三个方法结束，运行的线程ID为：5

            // 同一个方法，开始和结束的线程ID保持一致。
        }

        public static void Call2()
        {
            AsyncVsMultiThread.ExecuteMultithreading();
            Console.ReadLine();
        }

        // 异步编程适用场景：
        //  我们的程序逻辑中存在阻断操作。
        //  我们的应用有一个线程池并且有垂直扩展的需求。

        // 多线程编程适用场景：
        //  我们的程序逻辑存在相互独立的任务，任务与任务之间不相互干扰。
        //  我们存在多个可用的CPU内核数。

        // 总结：
        //  异步编程和多线程编程的区别在于侧重点不同，异步编程侧重于任务的执行顺序，而多线程编程则是关于多个线程如何并发执行最大限度利用CPU，两者对于提高程序可用性和性能方面起到了关键性的作用。
    }
}
